<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>颜色转换器与选择器</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            background-color: #f0f0f0;
        }
        .container {
            background-color: white;
            padding: 2rem;
            border-radius: 8px;
            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
            width: 350px;
        }
        h1 {
            text-align: center;
            margin-top: 0;
            color: #333;
        }
        .input-group {
            margin-bottom: 1rem;
        }
        label {
            display: block;
            margin-bottom: 0.5rem;
            font-weight: bold;
            color: #555;
        }
        input[type="text"] {
            width: calc(100% - 40px); /* 为按钮留出空间 */
            padding: 0.5rem;
            border: 1px solid #ddd;
            border-radius: 4px 0 0 4px;
            box-sizing: border-box;
            float: left;
        }
        .picker-btn {
            width: 40px;
            padding: 0.5rem;
            border: 1px solid #ddd;
            border-left: none;
            border-radius: 0 4px 4px 0;
            background-color: #f8f8f8;
            cursor: pointer;
            box-sizing: border-box;
            float: left;
        }
        .picker-btn:hover {
            background-color: #eaeaea;
        }
        .color-preview {
            width: 100%;
            height: 100px;
            border: 1px solid #ddd;
            border-radius: 4px;
            margin-top: 1rem;
            background-color: #fff; /* 默认白色 */
        }
        .error {
            color: red;
            font-size: 0.9rem;
            margin-top: 0.5rem;
            min-height: 1.2rem;
            clear: both; /* 清除浮动 */
            padding-top: 1rem;
        }
        .formats {
            display: flex;
            justify-content: space-between;
            margin-top: 1rem;
            font-size: 0.9rem;
            color: #666;
        }
        .format-value {
            font-family: monospace; /* 等宽字体，对齐更好看 */
        }
        /* 隐藏原生颜色选择器 */
        #nativeColorPicker {
            position: absolute;
            opacity: 0;
            width: 0;
            height: 0;
        }
    </style>
</head>
<body>

<div class="container">
    <h1>颜色转换器与选择器</h1>
    <div class="input-group">
        <label for="colorInput">输入或选择颜色:</label>
        <input type="text" id="colorInput" placeholder="#FF5733 或 rgb(255, 87, 51) 或 hsl(10, 100%, 50%)">
        <button class="picker-btn" id="pickerButton" title="使用颜色选择器">&#128153;</button> <!-- 调色板图标 -->
        <!-- 隐藏的原生颜色选择器 -->
        <input type="color" id="nativeColorPicker">
    </div>
    <div class="color-preview" id="colorPreview"></div>
    <div class="error" id="errorMessage"></div>
    <div class="formats">
        <div><strong>HEX:</strong> <span class="format-value" id="hexValue">#FFFFFF</span></div>
        <div><strong>RGB:</strong> <span class="format-value" id="rgbValue">rgb(255, 255, 255)</span></div>
        <div><strong>HSL:</strong> <span class="format-value" id="hslValue">hsl(0, 0%, 100%)</span></div>
    </div>
</div>

<script>
    const colorInput = document.getElementById('colorInput');
    const colorPreview = document.getElementById('colorPreview');
    const errorMessage = document.getElementById('errorMessage');
    const hexValue = document.getElementById('hexValue');
    const rgbValue = document.getElementById('rgbValue');
    const hslValue = document.getElementById('hslValue');
    const pickerButton = document.getElementById('pickerButton');
    const nativeColorPicker = document.getElementById('nativeColorPicker');

    // 更新颜色显示和格式
    function updateColor(colorStr) {
        try {
            // 清除旧错误
            errorMessage.textContent = '';
            
            // 尝试解析输入的颜色字符串
            const parsedColor = parseColorString(colorStr.trim());
            
            if (parsedColor) {
                const { r, g, b } = parsedColor;
                const hex = rgbToHex(r, g, b);
                const hsl = rgbToHsl(r, g, b);

                // 更新输入框
                colorInput.value = hex; // 统一显示为HEX

                // 更新预览
                colorPreview.style.backgroundColor = hex;

                // 更新格式显示
                hexValue.textContent = hex.toUpperCase();
                rgbValue.textContent = `rgb(${r}, ${g}, ${b})`;
                hslValue.textContent = `hsl(${Math.round(hsl.h)}, ${Math.round(hsl.s)}%, ${Math.round(hsl.l)}%)`;

            } else {
                throw new Error('无法识别的颜色格式');
            }

        } catch (e) {
            // 显示错误信息
            errorMessage.textContent = e.message || '输入格式错误';
            // 重置为默认状态
            // resetDisplay(); // 不重置，保留用户输入
        }
    }

    // 重置显示为默认状态
    function resetDisplay() {
        colorInput.value = '';
        colorPreview.style.backgroundColor = '#fff';
        hexValue.textContent = '#FFFFFF';
        rgbValue.textContent = 'rgb(255, 255, 255)';
        hslValue.textContent = 'hsl(0, 0%, 100%)';
    }

    // 解析颜色字符串
    function parseColorString(str) {
        let match;
        // HEX (#FFF or #FFFFFF)
        if ((match = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.exec(str))) {
            return hexToRgb(match[1]);
        }
        // RGB (e.g., rgb(255, 87, 51) or rgb(100% 20% 30%))
        else if ((match = /^rgb\(\s*(\d{1,3}%?)\s*,?\s*(\d{1,3}%?)\s*,?\s*(\d{1,3}%?)\s*\)$/.exec(str))) {
            return parseRgbValues(match);
        }
        // HSL (e.g., hsl(10, 100%, 50%) or hsl(10 100% 50%))
         // 注意：正则表达式修正，允许逗号或空格分隔
        else if ((match = /^hsl\(\s*(\d{1,3})\s*[, ]\s*(\d{1,3})%?\s*[, ]\s*(\d{1,3})%?\s*\)$/.exec(str))) {
            return hslToRgb(parseInt(match[1]), parseFloat(match[2]), parseFloat(match[3]));
        }
        return null;
    }

    // 解析RGB值，支持百分比
    function parseRgbValues(match) {
        const r = match[1];
        const g = match[2];
        const b = match[3];
        const parseValue = (valStr, maxVal) => {
            if (valStr.endsWith('%')) {
                return Math.round((parseFloat(valStr) / 100) * maxVal);
            } else {
                const val = parseInt(valStr, 10);
                if (val < 0 || val > maxVal) {
                     throw new Error(`RGB值 ${valStr} 超出范围 0-${maxVal}`);
                }
                return val;
            }
        };
        const rVal = parseValue(r, 255);
        const gVal = parseValue(g, 255);
        const bVal = parseValue(b, 255);
        
        // 再次检查解析后的值是否有效
        if ([rVal, gVal, bVal].some(v => isNaN(v) || v < 0 || v > 255)) {
             throw new Error('RGB值无效');
        }
        
        return { r: rVal, g: gVal, b: bVal };
    }

    // HEX to RGB
    function hexToRgb(hex) {
        // 处理 3 位简写
        const shorthandRegex = /^([a-f\d])([a-f\d])([a-f\d])$/i;
        hex = hex.replace(shorthandRegex, (m, r, g, b) => r + r + g + g + b + b);
        const result = /^([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
        return result ? {
            r: parseInt(result[1], 16),
            g: parseInt(result[2], 16),
            b: parseInt(result[3], 16)
        } : null;
    }

    // RGB to HEX
    function rgbToHex(r, g, b) {
        const toHex = (n) => {
            const hex = n.toString(16);
            return hex.length === 1 ? '0' + hex : hex;
        };
        return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
    }

    // RGB to HSL
    function rgbToHsl(r, g, b) {
        r /= 255;
        g /= 255;
        b /= 255;
        const max = Math.max(r, g, b), min = Math.min(r, g, b);
        let h, s, l = (max + min) / 2;

        if (max === min) {
            h = s = 0; // achromatic
        } else {
            const d = max - min;
            s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
            switch (max) {
                case r: h = (g - b) / d + (g < b ? 6 : 0); break;
                case g: h = (b - r) / d + 2; break;
                case b: h = (r - g) / d + 4; break;
            }
            h = ((h / 6) % 1) * 360; // 确保 h 在 0-360 范围内
        }

        return {
            h: h,
            s: s * 100,
            l: l * 100
        };
    }

    // HSL to RGB (用于颜色选择器返回的HEX转换)
    function hslToRgb(h, s, l) {
        h /= 360;
        s /= 100;
        l /= 100;
        let r, g, b;

        if (s === 0) {
            r = g = b = l; // achromatic
        } else {
            const hue2rgb = (p, q, t) => {
                if (t < 0) t += 1;
                if (t > 1) t -= 1;
                if (t < 1 / 6) return p + (q - p) * 6 * t;
                if (t < 1 / 2) return q;
                if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
                return p;
            };
            const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
            const p = 2 * l - q;
            r = hue2rgb(p, q, h + 1 / 3);
            g = hue2rgb(p, q, h);
            b = hue2rgb(p, q, h - 1 / 3);
        }

        return {
            r: Math.round(r * 255),
            g: Math.round(g * 255),
            b: Math.round(b * 255)
        };
    }


    // 事件监听
    colorInput.addEventListener('input', (e) => {
        updateColor(e.target.value);
    });

    // 点击按钮触发原生颜色选择器
    pickerButton.addEventListener('click', () => {
        nativeColorPicker.click();
    });

    // 原生颜色选择器值改变时
    nativeColorPicker.addEventListener('input', (e) => {
        const hex = e.target.value;
        updateColor(hex);
    });

    // 初始化
    updateColor('#FF5733'); // 设置一个初始颜色
</script>

</body>
</html>



